home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / winlib.lzh / WINLIB / WINDOWS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-04  |  22.0 KB  |  909 lines

  1. /********************************************************************
  2.  *                                                                    *
  3.  *    Window module                                                    *
  4.  *                                                                    *
  5.  *    Copyright (c) Clever Bits and Bitgate Software 1993 - 1994        *
  6.  *    All Rights Reserved.                                            *
  7.  *                                                                    *
  8.  *    All procedures that manipulates the window structure of            *
  9.  *    a window, as well as creating and killing windows.                *
  10.  *                                                                    *
  11.  ********************************************************************
  12.  *                                                                    *
  13.  *    Update log:                                                        *
  14.  *                                                                    *
  15.  *    [24.9.93] Ken Hollis                                            *
  16.  *                            - changed some code layout                *
  17.  *    [31.10.93] Karl A. 0ygard                                        *
  18.  *        WOpenWindow            - Changed xor'ing of win->state to |    *
  19.  *        WCloseWindow        - Changed xor'ing of win->state to &    *
  20.  *                            - It now takes a parameter which is        *
  21.  *                                passed to the dispatcher to tell it    *
  22.  *                                whether or not the dispatcher can    *
  23.  *                                stop the window from getting closed    *
  24.  *        WWindSet            - Removed () around window titles - I    *
  25.  *                                didn't like it.                        *
  26.  *        WWindSet            - pnameheader is renamed prgnameheader    *
  27.  *                            - prgnameheader is preformatted in WInit*
  28.  *        WCloseWindowNow        - renamed WCruelCloseWindow                *
  29.  *        WKillAllWindows        - made it nicer and more secure            *
  30.  *    [2.11.93 - 7.11.93] Karl A. 0ygard                                *
  31.  *                            - changed some code layout                *
  32.  *        WCreateWindow        - optimised                                *
  33.  *        WMoveWindow            - changed way sizing of windows from    *
  34.  *                                dialogs work. Somewhat better.        *
  35.  *    [3.12.93 - 29.3.93] Ken Hollis                                    *
  36.  *                            - added window elements as dialog box    *
  37.  *        WInitElements        - added to fix object elements            *
  38.  *        WWindSet            - added support for window iconification*
  39.  *                            - fixed up iconification routines a bit    *
  40.  *                            - fixed name concatenation                *
  41.  *        WRedrawAllWindows    - added                                    *
  42.  *        WCreateWindow        - added popup information clearing        *
  43.  *                            - added text loading support            *
  44.  *        WReassignWindow        - added for dialog reassignment            *
  45.  *        WRedrawWindowLevel    - added for drawing different object    *
  46.  *                                levels (optimizes redraw speed)        *
  47.  *        WCreateWindow        - added bug fix to top W_UNUNTOPPABLE    *
  48.  *                                window if there is one; must be done*
  49.  *                            - added treenumber item to window        *
  50.  *        WTopWindow            - added dominance checking for topping    *
  51.  *                                                                    *
  52.  ********************************************************************/
  53.  
  54. #include <string.h>
  55. #include <stddef.h>
  56. #include <stdlib.h>
  57. #include <stdio.h>
  58. #include <tos.h>
  59.  
  60. #include "winlib.h"
  61.  
  62. #ifdef __TURBOC__
  63. #pragma warn -pia
  64. #endif
  65.  
  66. #ifndef __WINDOWS__
  67. #define __WINDOWS__
  68. #endif
  69.  
  70. /*
  71.  *    Set window parameters
  72.  *
  73.  *    Same parameters as wind_set except for
  74.  *
  75.  *    win = window in which to set parameters
  76.  *
  77.  *    This procedure is an interception of wind_set in order to ensure that
  78.  *    the application sets correct information. (Censorship!)
  79.  */
  80. GLOBAL int WWindSet(WINDOW *win, int wi_sfield, ...)
  81. {
  82.     va_list    argptr;
  83.     int wi_sw1, wi_sw2, wi_sw3, wi_sw4;
  84.     long wi_sl1;
  85.  
  86.     switch (wi_sfield) {
  87.         case WF_TOP:
  88.             wind_set(win->handle, WF_TOP);
  89.             if (win->prev)                                    /* Bring window to top of WindowChain */
  90.                 win->prev->next = win->next;
  91.             win->next->prev = win->prev;
  92.         
  93.             if (WindowChain == win)
  94.                 WindowChain = win->next;
  95.         
  96.             WindowChain->prev = win;
  97.             win->next = WindowChain;
  98.             win->prev = NULL;
  99.             WindowChain = win;
  100.             return TRUE;
  101.  
  102.         case WF_MODAL:
  103.         case WF_BEVENT:
  104.         case WF_MINIMIZE:
  105.         case WF_UNUNTOPPABLE:
  106.             va_start(argptr, wi_sfield);
  107.             wi_sw1 = va_arg(argptr, int);
  108.             va_end(argptr);
  109.  
  110.             switch (wi_sfield) {
  111.                 case WF_MODAL:
  112.                     if (wi_sw1)
  113.                         win->state |= W_MODAL;
  114.                     else
  115.                         win->state &= ~W_MODAL;
  116.  
  117.                     return TRUE;
  118.  
  119.                 case WF_BEVENT:
  120.                     if (AES_VERSION >= 0x0400)
  121.                         wind_set(win->handle, WF_BEVENT, wi_sw1 ? 1 : 0);
  122.  
  123.                     if (wi_sw1)
  124.                         win->state |= W_BEVENT;
  125.                     else
  126.                         win->state &= ~W_BEVENT;
  127.                     return TRUE;
  128.  
  129.                 case WF_MINIMIZE:
  130.                     if (wi_sw1)
  131.                         win->state |= W_MINIMIZED;
  132.                     else
  133.                         win->state &= ~W_MINIMIZED;
  134.  
  135.                     WWindSet(win, WF_CURRXYWH, -1, -1, -1, win->size.g_h);
  136.                     return TRUE;
  137.  
  138.                 case WF_UNUNTOPPABLE:
  139.                     if (wi_sw1)
  140.                         win->state |= W_UNUNTOPPABLE;
  141.                     else
  142.                         win->state &= ~W_UNUNTOPPABLE;
  143.  
  144.                     WWindSet(win, WF_TOP);
  145.                     return TRUE;
  146.             }
  147.  
  148.         case WF_TIMER:
  149.             if (wi_sw1)
  150.                 win->state |= W_TIMER;
  151.             else
  152.                 win->state &= ~W_TIMER;
  153.  
  154.             return TRUE;
  155.  
  156.         case WF_DIALOG:
  157.             if (wi_sw1)
  158.                 win->state |= W_DIALOG;
  159.             else
  160.                 win->state &= ~W_DIALOG;
  161.  
  162.             return TRUE;
  163.  
  164.         case WF_NAME:
  165.         case WF_INFO:
  166.             va_start(argptr, wi_sfield);
  167.             wi_sl1 = va_arg(argptr, long);
  168.             va_end(argptr);
  169.  
  170.             switch (wi_sfield) {
  171.                 case WF_NAME:
  172.                     sprintf(win->origtitle, "%s", wi_sl1);
  173.  
  174.                     if (win->state & W_DIALOG)
  175.                         sprintf(win->title, "[ %s%s ]", prgnameheader, wi_sl1);
  176.                     else
  177.                         sprintf(win->title, "%s%s", prgnameheader, wi_sl1);
  178.  
  179.                     return wind_set(win->handle, WF_NAME, win->title);
  180.  
  181.                 case WF_INFO:
  182.                     strncpy(win->info, (char *) wi_sl1, 128);
  183.                     return wind_set(win->handle, WF_INFO, win->info);
  184.             }
  185.  
  186.         case WF_ICONIFY:
  187.             va_start(argptr, wi_sfield);
  188.             wi_sw1 = va_arg(argptr, int);
  189.             wi_sw2 = va_arg(argptr, int);
  190.             wi_sw3 = va_arg(argptr, int);
  191.             wi_sw4 = va_arg(argptr, int);
  192.             va_end(argptr);
  193.  
  194.             win->state |= W_ICONIFIED;
  195. /*            if (AES_VERSION>=0x0400)
  196.                 wind_set(win->handle, WF_ICONIFY, wi_sw1, wi_sw2, wi_sw3, wi_sw4);
  197.             else */
  198.  
  199.             if (WCallIconifyDispatcher(win, TRUE))
  200.                 WIconify(win);
  201.  
  202.             return TRUE;
  203.  
  204.         default:
  205.             va_start(argptr, wi_sfield);
  206.             wi_sw1 = va_arg(argptr, int);
  207.             wi_sw2 = va_arg(argptr, int);
  208.             wi_sw3 = va_arg(argptr, int);
  209.             wi_sw4 = va_arg(argptr, int);
  210.             va_end(argptr);
  211.  
  212.             switch (wi_sfield) {
  213.                 case WF_CURRXYWH:
  214.                     WMoveWindow(win, wi_sw1, wi_sw2, wi_sw3, wi_sw4);
  215.                     return TRUE;
  216.  
  217. /*                case WF_ICONIFY:
  218.                     win->state |= W_ICONIFIED;
  219.                     if (AES_VERSION>=0x0400)
  220.                         wind_set(win->handle, WF_ICONIFY, wi_sw1, wi_sw2, wi_sw3, wi_sw4);
  221.                     else
  222.                         WIconify(win);
  223.                     return TRUE; */
  224.  
  225.                 case WF_UNICONIFY:
  226.                     win->state &= ~W_ICONIFIED;
  227.                     wind_set(win->handle, WF_UNICONIFY, wi_sw1, wi_sw2, wi_sw3, wi_sw4);
  228.                     return TRUE;
  229.  
  230.                 default:
  231.                     return wind_set(win->handle, wi_sfield, wi_sw1, wi_sw2, wi_sw3, wi_sw4);
  232.             }
  233.     }
  234. }
  235.  
  236.  
  237. /*
  238.  *    Get window parameters
  239.  *
  240.  *    Same parameters as wind_get except for
  241.  *    win = WINDOW to get parameters from
  242.  *
  243.  *    This procedure is an interception of wind_get in order to ensure that
  244.  *    the application gets correct information. (Censorship.)
  245.  */
  246. GLOBAL int WWindGet(WINDOW *win, int wi_gfield, ...)
  247. {
  248.     va_list    argptr;
  249.     int ret, *wi_gw1, *wi_gw2, *wi_gw3, *wi_gw4;
  250.     
  251.     va_start(argptr, wi_gfield);
  252.     wi_gw1 = va_arg(argptr, int *);
  253.     wi_gw2 = va_arg(argptr, int *);
  254.     wi_gw3 = va_arg(argptr, int *);
  255.     wi_gw4 = va_arg(argptr, int *);
  256.     va_end(argptr);
  257.  
  258.     switch (wi_gfield) {
  259.         case WF_WORKXYWH:
  260.             if (ret = wind_get(win->handle, WF_WORKXYWH, wi_gw1, wi_gw2, wi_gw3, wi_gw4))
  261.                 if (win->menubar)
  262.                     if (win->handle > 0) {
  263.                         int h;
  264.  
  265.                         h = *wi_gw4 - win->menubar[1].ob_height + 1 < 0 ? *wi_gw4 : win->menubar[1].ob_height + 1;
  266.                         *wi_gw4 -= h;
  267.                         *wi_gw2 += h;
  268.                     }
  269.             return ret;
  270.  
  271.         default:
  272.             return wind_get(win->handle, wi_gfield, wi_gw1, wi_gw2, wi_gw3, wi_gw4);
  273.     }
  274. }
  275.  
  276.  
  277. /*
  278.  *    Open a window
  279.  *
  280.  *    Returns TRUE upon success
  281.  */
  282. GLOBAL int WOpenWindow(WINDOW *win)
  283. {
  284.     if (!(win->state & W_OPEN)) {
  285.         if (!wind_open(win->handle, win->size.g_x, win->size.g_y, win->size.g_w, win->size.g_h))
  286.             return FALSE;
  287.  
  288.         win->state |= W_OPEN;                /* Set state to "open" */
  289.         win->state &= ~W_ICONIFIED;
  290.     }
  291.  
  292.     return TRUE;
  293. }
  294.  
  295.  
  296. /*
  297.  *    Ask a window to close
  298.  *
  299.  *    Sends a request to the window to kindly close
  300.  *
  301.  *    message = WC_OBJECTABLE    - window may protest
  302.  *              WC_NOTOBJECTABLE - window may not protest
  303.  *
  304.  *    win = Window to close (if NULL, top window will be closed)
  305.  */
  306. GLOBAL void WCloseWindow(WINDOW *win, int message)
  307. {
  308.     int msg_buf[8];
  309.  
  310.     if (!win)
  311.         win = WindowChain;
  312.  
  313.     if (win->next)
  314.     {
  315.         msg_buf[0] = WM_CLOSED;
  316.         msg_buf[1] = Ap_ID;
  317.         msg_buf[2] = 0;
  318.         msg_buf[3] = win->handle;
  319.         msg_buf[4] = message;
  320.  
  321.         WMsgWindow(win, msg_buf);
  322.     }
  323. }
  324.  
  325.  
  326. /*
  327.  *    Close a window
  328.  *
  329.  *    Closes the window without notifying the window about it.
  330.  *    Call WCloseWindow with the WC_NOTOBJECTABLE parameter,
  331.  *    rather than closing it. It is not nice.
  332.  *
  333.  *    win = Window to close (if NULL, top window will be closed)
  334.  */
  335. GLOBAL void WCruelCloseWindow(WINDOW *win, BOOL icon)
  336. {
  337.     if (!win)
  338.         win = WindowChain;
  339.  
  340.     win->edit_disp = FALSE;
  341.  
  342.     if (win->next && win->state & W_OPEN) {
  343.         if (wind_close(win->handle)) {
  344.             if (icon) {
  345.                 win->state &= ~W_OPEN;            /* Set state to not open */
  346.                 win->state |= W_ICONIFIED;
  347.             } else
  348.                 win->state &= ~W_OPEN;
  349.  
  350.             graf_shrinkbox(desk.g_w / 2, desk.g_h / 2, 2, 2, win->size.g_x, win->size.g_y, win->size.g_w, win->size.g_h);
  351.             return;
  352.         }
  353.     }
  354. }
  355.  
  356.  
  357. /*
  358.  *    Ask a window to die
  359.  *
  360.  *    Call WNiceCloseWindow, rather than killing it. It is not
  361.  *    nice.
  362.  *
  363.  *    win = Window to kill (if NULL, top window will be closed)
  364.  */
  365. GLOBAL void WKillWindow(WINDOW *win)
  366. {
  367.     int msg_buf[8];
  368.  
  369.     if (!win)
  370.         win = WindowChain;
  371.  
  372.     if (win->next)
  373.     {
  374.         msg_buf[0] = WM_KILL;
  375.         msg_buf[1] = Ap_ID;
  376.         msg_buf[2] = 0;
  377.         msg_buf[3] = win->handle;
  378.     
  379.         WMsgWindow(win, msg_buf);
  380.     }
  381. }
  382.  
  383.  
  384. /*
  385.  *    Create a new window
  386.  *
  387.  *    state = state of new window
  388.  *                W_OPEN                  = automatically opened
  389.  *                W_MINIMIZED              = "minimized"
  390.  *                W_UNUNTOPPABLE          = un-untoppable window
  391.  *                                        (i.e. requires full attention - should be used with W_MODAL)
  392.  *                W_FULLERMINIMIZES      = window is minimized rather than fulled when FULLER is selected
  393.  *                W_BACKGROUND          = window which can be clicked in in the background
  394.  *                W_MODAL               = window which blocks mouse clicks to all other windows, 
  395.  *                                        *even* if they have the W_BACKGROUND mode
  396.  *                                        (i.e. requires full attention - should be used with W_UNUNTOPPABLE)
  397.  *    kind = Attributes of the window (see wi_crkind in wind_create)
  398.  *    title = title string to use for title of window (none if 0)
  399.  *    info = info string to use for infofield of window (none if 0)
  400.  *    object = Resource object to put in window (none if -1)
  401.  *    edobject = First editable field in resource object (none if 0)
  402.  *    menubar = Resource object number of the menubar to put in window (none if -1)
  403.  *    WndDispatcher = a pointer to the windowdispatcher of the window.
  404.  *     (may be left 0, meaning that WinLIB will deal with it.)
  405.  *    user = user definable pointer (is put into the WINDOW structure of
  406.  *     the window, and may be used freely)
  407.  *    x, y, w, h = physical size of window
  408.  *     (any parameters that are -1 will be taken from the centered
  409.  *      resource (if any))
  410.  *
  411.  *    Returns: pointer to created window structure
  412.  *             NOMORE if no windows are available, 
  413.  *             FALSE on any other failure
  414.  */
  415. GLOBAL WINDOW *WCreateWindow(int state, int style, int kind, 
  416.                               char *title, char *info, 
  417.                               int object, int edobject, 
  418.                               int menubar, 
  419.                               int WndDispatcher(WINDOW *, int[]), 
  420.                               void *user, 
  421.                               int x, int y, int w, int h,
  422.                               OBJECT *obj, int dominance)
  423. {
  424.     WINDOW *ptr;
  425.     int pops;
  426.  
  427.     if (ptr = malloc(sizeof(WINDOW))) {
  428.         int msg_buf[8];
  429.  
  430.         ptr->state = 0;
  431.         ptr->style = 0;
  432.         ptr->user = user;
  433.         ptr->kind = kind;
  434.         ptr->edobject = edobject;
  435.         ptr->edpos = -1;
  436.         ptr->edit_disp = FALSE;
  437.  
  438.         ptr->has_edit = (edobject) ? TRUE : FALSE;
  439.         ptr->dominance = dominance;
  440.  
  441.         ptr->WndDispatcher = malloc(sizeof(WndDispatcher));
  442.         ptr->WndDispatcher = WndDispatcher;
  443.  
  444.         ptr->timer.clock = 0x00000000;
  445.         ptr->timer.ev_mtcount = 0x00000000;
  446.         ptr->timer.user = NULL;
  447.         ptr->timer.status = FALSE;
  448.  
  449.         if (menubar != -1) {
  450.             rsrc_gaddr(R_TREE, menubar, &(ptr->menubar));
  451.             ptr->menubar[1].ob_spec.obspec.framesize = -1;
  452.         } else 
  453.             ptr->menubar = NULL;
  454.  
  455.         if (obj || object != -1) {
  456.             int x2, y2, w2, h2;
  457.  
  458.             if (object != -1) {
  459.                 rsrc_gaddr(R_TREE, object, &(ptr->tree));
  460.                 ptr->treenumber = object;
  461.             } else {
  462.                 ptr->tree = obj;
  463.                 ptr->treenumber = -1;
  464.             }
  465.  
  466.             form_center(ptr->tree, &x2, &y2, &w2, &h2);
  467.  
  468.             x2 += abs(ptr->tree->ob_spec.obspec.framesize);
  469.             y2 += abs(ptr->tree->ob_spec.obspec.framesize);
  470.             w2 -= abs(ptr->tree->ob_spec.obspec.framesize) * 2;
  471.             h2 -= abs(ptr->tree->ob_spec.obspec.framesize) * 2;
  472.  
  473.             wind_calc(WC_BORDER, ptr->kind, x2, y2, w2, h2, &x2, &y2, &w2, &h2);
  474.  
  475.             x = (x != -1) ? x : x2;
  476.             y = (y != -1) ? y : y2;
  477.             w = (w != -1) ? w : w2;
  478.             h = (h != -1) ? h : h2;
  479.         } else {
  480.             ptr->tree = NULL;
  481.  
  482.             x = (x != -1) ? x : 0;
  483.             y = (y != -1) ? y : 0;
  484.             w = (w != -1) ? w : 1;
  485.             h = (h != -1) ? h : 1;
  486.         }
  487.  
  488.         if (menubar != -1)
  489.             h += ptr->menubar[1].ob_height + 1;
  490.  
  491.         ptr->size.g_x = x;
  492.         ptr->size.g_y = y;
  493.         ptr->size.g_w = w;
  494.         ptr->size.g_h = h;
  495.  
  496.                                                     /* Create new window */
  497.         if ((ptr->handle = wind_create(ptr->kind, x, y, w, h)) < 0) {
  498.             free(ptr);
  499.             return (WINDOW *) NOMORE;
  500.         }
  501.  
  502.         WindowChain->prev = ptr;                    /* Insert window in chain */
  503.         ptr->next = WindowChain;
  504.         ptr->prev = NULL;
  505.         WindowChain = ptr;
  506.  
  507.         graf_growbox(desk.g_w / 2, desk.g_h / 2, 2, 2, ptr->size.g_x, ptr->size.g_y, ptr->size.g_w, ptr->size.g_h);
  508.  
  509.         if (state & W_FULLERMINIMIZES)
  510.             ptr->state |= W_FULLERMINIMIZES;
  511.  
  512.         if (info)
  513.             WWindSet(ptr, WF_INFO, info);
  514.  
  515.         if (state & W_OPEN)
  516.             WOpenWindow(ptr);
  517.  
  518.         if (state & W_MINIMIZED)
  519.             WWindSet(ptr, WF_MINIMIZE, 1);
  520.  
  521.         if (state & W_UNUNTOPPABLE)
  522.             WWindSet(ptr, WF_UNUNTOPPABLE, 1);
  523.  
  524.         if (state & W_BEVENT)
  525.             WWindSet(ptr, WF_BEVENT, 1);
  526.  
  527.         if (state & W_MODAL)
  528.             WWindSet(ptr, WF_MODAL, 1);
  529.  
  530.         if (state & W_TIMER)
  531.             WWindSet(ptr, WF_TIMER, 1);
  532.  
  533.         if (state & W_DIALOG)
  534.             WWindSet(ptr, WF_DIALOG, 1);
  535.  
  536.         if (title)
  537.             WWindSet(ptr, WF_NAME, title);
  538.  
  539.         if (state & W_FULLERICONIFIES)
  540.             ptr->state |= W_FULLERICONIFIES;
  541.  
  542.         if (style & S_FULLERMINIMIZES)
  543.             ptr->style |= S_FULLERMINIMIZES;
  544.  
  545.         if (style & S_FULLERICONIFIES)
  546.             ptr->style |= S_FULLERICONIFIES;
  547.  
  548.         if (style & S_FULLERCHOOSES)
  549.             ptr->style |= S_FULLERCHOOSES;
  550.  
  551.         if (style & S_MULTICOPYABLE)
  552.             ptr->style |= S_MULTICOPYABLE;
  553.  
  554.         vsl_color(VDIhandle, BLACK);
  555.  
  556.         msg_buf[0] = WM_CREATED;
  557.         msg_buf[1] = Ap_ID;
  558.         msg_buf[2] = 0;
  559.         msg_buf[3] = ptr->handle;
  560.         WMsgWindow(ptr, msg_buf);
  561.  
  562.         WTopWindow(ptr);
  563.  
  564.         return ptr;
  565.     }
  566.  
  567.     return FALSE;
  568. }
  569.  
  570. /*
  571.  *    Move/resize window
  572.  *
  573.  *    win = Window to move
  574.  *    x = new x coordinate
  575.  *    y = new y coordinate
  576.  *    w = new width
  577.  *    h = new height
  578.  *
  579.  *    Any parameters that are -1 are taken from the current settings of the window.
  580.  */
  581. GLOBAL void WMoveWindow(WINDOW *win, int x, int y, int w, int h)
  582. {
  583.     int wx, wy, ww, wh;
  584.  
  585.     wind_get(win->handle, WF_CURRXYWH, &wx, &wy, &ww, &wh);
  586.  
  587.     x = (x == -1) ? wx : (win->size.g_x = x);
  588.     y = (y == -1) ? wy : (win->size.g_y = y);
  589.     w = (w == -1) ? ww : w;
  590.     h = (h == -1) ? wh : h;
  591.  
  592.     if (win->state & W_MINIMIZED)
  593.         if (w != ww || h != wh )
  594.             win->state &= ~W_MINIMIZED;
  595.         else {
  596.             int dummy, height;
  597.  
  598.             wind_get(win->handle, WF_WORKXYWH, &dummy, &dummy, &dummy, &height);
  599.             if (h > wh - height)
  600.                 h = wh - height;
  601.         }
  602.  
  603.     if (!(win->state & W_MINIMIZED)) {
  604.         win->size.g_w = w;
  605.         win->size.g_h = h;
  606.     }
  607.  
  608.     if (x != wx || y != wy || w != ww || h != wh)            /* If either parameter has changed... */
  609.         wind_set(win->handle, WF_CURRXYWH, x, y, w, h);    /* Move window */
  610.  
  611.     WWindGet(win, WF_WORKXYWH, &x, &y, &w, &h);
  612.  
  613.     if (win->tree) {
  614.         win->tree->ob_x = x - (win->tree->ob_type & 0xff00 ? win->tree->ob_spec.obspec.framesize : 0);
  615.         win->tree->ob_y = y - (win->tree->ob_type & 0xff00 ? win->tree->ob_spec.obspec.framesize : 0);
  616.     }
  617.  
  618.     if (win->menubar)
  619.         if (win->handle > 0) {
  620.             win->menubar->ob_x = x;
  621.             win->menubar->ob_y = y - win->menubar[1].ob_height - 1;
  622.         }
  623. }
  624.  
  625.  
  626. /*
  627.  *    Top window
  628.  *
  629.  *    win = Window to bring to top
  630.  *
  631.  *    If win = 0, bottommost window (if any) is topped
  632.  */
  633. GLOBAL void WTopWindow(WINDOW *win)
  634. {
  635.     int dominanthandle;
  636.  
  637.     if (!win) {
  638.         if ((win = WindowChain)->next)
  639.             if (WindowChain->state & W_UNUNTOPPABLE)
  640.                 while ((win->next->next) && (win->next->state & W_UNUNTOPPABLE) &&
  641.                         (win->next->dominance != D_NONE)) {
  642.                     if (dominanthandle = WFindDominance()) {
  643.                         WINDOW *dom;
  644.  
  645.                         dom = WLocateWindow('HNDL', dominanthandle);
  646.  
  647.                         if (dom->dominance == D_ALWAYSTOP) {
  648.                             WWindSet(dom, WF_TOP, dominanthandle);
  649.                             return;
  650.                         }
  651.                     }
  652.  
  653.                     win = win->next;
  654.                 }
  655.             else
  656.                 while (win->next->next)
  657.                     win = win->next;
  658.         else
  659.             return;
  660.     } else {
  661.         WINDOW *newwin = WindowChain;
  662.  
  663.         if (newwin->state & W_UNUNTOPPABLE)
  664.             if (win->dominance == D_ALWAYSTOP) {
  665.                 WINDOW *dom;
  666.  
  667.                 dom = WLocateWindow('HNDL', win->handle);
  668.  
  669.                 if (dom->dominance == D_ALWAYSTOP) {
  670.                     WWindSet(dom, WF_TOP, win->handle);
  671.                     return;
  672.                 }
  673.             }
  674.  
  675.             if (win->dominance == D_SWITCHABLE)
  676.                 if (dominanthandle = WFindDominance()) {
  677.                     WINDOW *dom;
  678.  
  679.                     dom = WLocateWindow('HNDL', dominanthandle);
  680.  
  681.                     if (dom->dominance == D_ALWAYSTOP) {
  682.                         WWindSet(dom, WF_TOP, dominanthandle);
  683.                         return;
  684.                     }
  685.                 }
  686.  
  687.             if (dominanthandle = WFindDominance()) {
  688.                 WINDOW *dom;
  689.  
  690.                 dom = WLocateWindow('HNDL', dominanthandle);
  691.  
  692.                 if (dom->dominance == D_ALWAYSTOP) {
  693.                     WWindSet(dom, WF_TOP, dominanthandle);
  694.                     return;
  695.                 }
  696.             }
  697.  
  698.         if (newwin->next)
  699.             newwin = newwin->next;
  700.         else
  701.             return;
  702.     }
  703.  
  704.     WWindSet(win, WF_TOP, win->handle);
  705. }
  706.  
  707.  
  708. /*
  709.  *    Redraw rectangle of a window
  710.  *
  711.  *    win = window to redraw
  712.  *    x = x coord
  713.  *    y = y coord
  714.  *    w = width
  715.  *    h = height
  716.  *
  717.  *    (This procedure really just sends a message to the window dispatcher
  718.  *     of the window to repaint the actual rectangle.)
  719.  */
  720. GLOBAL void WRedrawWindow(WINDOW *win, int x, int y, int w, int h)
  721. {
  722.     int msg_buf[8];
  723.  
  724.     msg_buf[0] = WM_REDRAW;
  725.     msg_buf[1] = Ap_ID;
  726.     msg_buf[2] = 0;
  727.     msg_buf[3] = win->handle;
  728.     msg_buf[4] = x;
  729.     msg_buf[5] = y;
  730.     msg_buf[6] = w;
  731.     msg_buf[7] = h;
  732.  
  733.     WMsgWindow(win, msg_buf);
  734. }
  735.  
  736. GLOBAL void WRedrawWindowLevel(WINDOW *win, int xx, int yy, int ww, int hh, int object, int level)
  737. {
  738.     GRECT realrect, temp, work;
  739.     int pxyarray[4], msg_buf[8], tophandle;
  740.  
  741.     WWindGet(win, WF_TOP, &tophandle);
  742.  
  743.     if (win->edobject && win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  744.         objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
  745.         win->edit_disp = FALSE;
  746.     }
  747.  
  748.     realrect.g_x = xx;
  749.     realrect.g_y = yy;
  750.     realrect.g_w = ww;
  751.     realrect.g_h = hh;
  752.  
  753.     msg_buf[0] = WM_REDRAW;
  754.     msg_buf[1] = msg_buf[2] = 0;
  755.     msg_buf[3] = win->handle;
  756.     msg_buf[4] = xx;
  757.     msg_buf[5] = yy;
  758.     msg_buf[6] = ww;
  759.     msg_buf[7] = hh;
  760.  
  761.     if (win->menubar)
  762.         if (win->handle > 0) {
  763.             int x, y, dummy;
  764.  
  765.             WUpdateWindowMenu(win, msg_buf[4], msg_buf[5], msg_buf[6], msg_buf[7]);
  766.             objc_offset(win->menubar, 1, &x, &y);
  767.             dummy = max(msg_buf[5], y + win->menubar[1].ob_height + 1);
  768.             if (dummy > msg_buf[5]) {
  769.                 msg_buf[7] -= dummy - msg_buf[5];
  770.                 msg_buf[5] = dummy;
  771.             }
  772.         }
  773.  
  774.     if (rc_intersect(&realrect, &desk)) {
  775.         WWindGet(win, WF_WORKXYWH, &work.g_x, &work.g_y, &work.g_w, &work.g_h);
  776.  
  777.         if (rc_intersect(&realrect, &work))
  778.             if (msg_buf[7] > 0 && WCallWndDispatcher(win, msg_buf))
  779.                 if (win->tree)
  780.                     WUpdateWindowDlgLevel(win, msg_buf[4], msg_buf[5], msg_buf[6], msg_buf[7], object, level);
  781.                 else {    
  782.                     wind_update(BEG_UPDATE);
  783.                     graf_mouse(M_OFF, NULL);
  784.  
  785.                     vsf_interior(VDIhandle, FIS_SOLID);
  786.                     vswr_mode(VDIhandle, MD_REPLACE);
  787.                     vsf_color(VDIhandle, 0);
  788.  
  789.                     WWindGet(win, WF_FIRSTXYWH, &temp.g_x, &temp.g_y, &temp.g_w, &temp.g_h);
  790.                     while (temp.g_w && temp.g_h) {
  791.                         if (rc_intersect(&temp, &realrect)) {
  792.                             pxyarray[0] = temp.g_x;
  793.                             pxyarray[1] = temp.g_y;
  794.                             pxyarray[2] = temp.g_x + temp.g_w - 1;
  795.                             pxyarray[3] = temp.g_y + temp.g_h - 1;
  796.  
  797.                             v_bar(VDIhandle, pxyarray);
  798.                         }
  799.                         WWindGet(win, WF_NEXTXYWH, &temp.g_x, &temp.g_y, &temp.g_w, &temp.g_h);
  800.                     }
  801.  
  802.                     graf_mouse(M_ON, NULL);
  803.                     wind_update(END_UPDATE);
  804.                 }
  805.     }
  806.  
  807.     if (win->edobject && !win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
  808.         objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
  809.         win->edit_disp = TRUE;
  810.     }
  811. }
  812.  
  813. /*
  814.  *    Kills all windows
  815.  *
  816.  *    First asks all windows to terminate immediately,
  817.  *    then kills any windows that still might hang around.
  818.  */
  819. GLOBAL void WKillAllWindows(void)
  820. {
  821.     WINDOW *win = WindowChain;
  822.  
  823.     while (win->next) {
  824.         win = win->next;
  825.         WCloseWindow(win->prev, WC_NOTOBJECTABLE);
  826.     }
  827.  
  828.     while (WindowChain->next)
  829.         WKillWindow(WindowChain);
  830. }
  831.  
  832.  
  833. /*
  834.  *    Redraw all windows
  835.  *
  836.  *    win = Window to bring to top
  837.  *
  838.  *    If win = 0, bottommost window (if any) is topped
  839.  */
  840. GLOBAL void WRedrawAllWindows(void)
  841. {
  842.     WINDOW *win = WindowChain;
  843.  
  844.     while (win->next) {
  845.         win = win->next;
  846.         WRedrawWindow(win->prev, win->prev->size.g_x,
  847.                         win->prev->size.g_y, win->prev->size.g_w,
  848.                         win->prev->size.g_h);
  849.     }
  850. }
  851.  
  852. /*
  853.  *    Find WINDOW structure
  854.  *
  855.  *    ident = 4 byte identification structure
  856.  *    ...      = information to search for
  857.  */
  858. GLOBAL WINDOW *WLocateWindow(long ident, ...)
  859. {
  860.     WINDOW *win = WindowChain;
  861.     va_list argptr;
  862.     int intparm;
  863.     OBJECT *intobj;
  864.  
  865.     switch((long)(ident)) {
  866.         case 'HNDL':
  867.         case 'STAT':
  868.         case 'KIND':
  869.         case 'EOBJ':
  870.         case 'EPOS':
  871.         case 'HASE':
  872.         case 'EDSP':
  873.         case 'TPLN':
  874.         case 'AMTM':
  875.         case 'TOP_':
  876.         case 'ICON':
  877.             va_start(argptr, 1);
  878.             intparm = va_arg(argptr, int);
  879.             va_end(argptr);
  880.             break;
  881.  
  882.         case 'TREE':
  883.             va_start(argptr, 1);
  884.             intobj = va_arg(argptr, OBJECT *);
  885.             va_end(argptr);
  886.             break;
  887.     }
  888.  
  889.     while(win->next) {
  890.         switch((long)(ident)) {
  891.             case 'HNDL':
  892.                 if (win->handle == intparm)
  893.                     return(win);
  894.                 break;
  895.  
  896.             case 'ICON':
  897.                 if (win->objnumber == intparm)
  898.                     return(win);
  899.                 break;
  900.  
  901.             case 'TREE':
  902.                 if (win->tree == intobj)
  903.                     return(win);
  904.                 break;
  905.         }
  906.         win = win->next;
  907.     }
  908.     return((WINDOW *) 0L);
  909. }